package com.yangwei.examination.teacher.controller;

import com.baomidou.mybatisplus.core.toolkit.Wrappers;
import com.yangwei.examination.student.pojo.AnswerPaper;
import com.yangwei.examination.student.pojo.AnswerPaperChoice;
import com.yangwei.examination.student.pojo.AnswerPaperQuestion;
import com.yangwei.examination.student.service.AnswerPaperChoiceService;
import com.yangwei.examination.student.service.AnswerPaperQuestionService;
import com.yangwei.examination.student.service.AnswerPaperService;
import com.yangwei.examination.teacher.model.StatisticStudent;
import com.yangwei.examination.teacher.pojo.*;
import com.yangwei.examination.teacher.service.*;
import com.yangwei.examination.user.pojo.Student;
import com.yangwei.examination.user.pojo.User;
import com.yangwei.examination.user.service.StudentService;
import com.yangwei.examination.utils.ReportCsvUtils;
import com.yangwei.examination.utils.ResultUtils;
import com.yangwei.examination.utils.ResultVo;
import io.swagger.annotations.Api;
import io.swagger.annotations.ApiOperation;
import org.apache.commons.lang.SerializationUtils;
import org.apache.commons.lang.StringUtils;
import org.springframework.beans.BeanUtils;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.util.CollectionUtils;
import org.springframework.web.bind.annotation.*;
import org.springframework.web.context.request.RequestContextHolder;
import org.springframework.web.context.request.ServletRequestAttributes;
import org.supercsv.cellprocessor.ift.CellProcessor;
import org.supercsv.util.CsvContext;

import javax.annotation.Resource;
import java.util.*;
import java.util.stream.Collectors;
@Api(tags = "教师批改答卷",description = "改卷相关")
@RestController
@RequestMapping("/tea")
public class CorrectAnswerPaperController {

    @Resource
    private AnswerPaperService answerPaperService;

    @Resource
    private PaperService paperService;

    @Resource
    private PaperQuestionService paperQuestionService;

    @Resource
    private PaperQuestionAnswerService paperQuestionAnswerService;

    @Resource
    private AnswerPaperQuestionService answerPaperQuestionService;

    @Resource
    private AnswerPaperChoiceService answerPaperChoiceService;

    @Resource
    private StudentService studentService;

    @Resource
    private ExamService examService;

    @Resource
    private CorrectAnswerPaperService correctAnswerPaperService;

    @Resource
    private CorrectAnswerPaperInfoService correctAnswerPaperInfoService;

    @Resource
    private CorrectAnswerPaperScoreService correctAnswerPaperScoreService;

    //查本班将批改的答卷
    @ApiOperation("查本班将批改的答卷")
    @PostMapping("/getAnswerPaperInfoList")
    public ResultVo getAnswerPaperInfoList(@RequestBody Exam exam) {

        //*查答卷列表  只有填空题简答题需要批改
        List<AnswerPaper> answerPaperList = answerPaperService.list(Wrappers.lambdaQuery(AnswerPaper.class)
                .eq(AnswerPaper::getExamId, exam.getId())
        );

        for (AnswerPaper answerPaper : answerPaperList) {
            //查答卷问题
            List<AnswerPaperQuestion> answerPaperQuestionList = answerPaperQuestionService.list(Wrappers.lambdaQuery(AnswerPaperQuestion.class)
                    .eq(AnswerPaperQuestion::getAnswerPaperId, answerPaper.getId())
                    .and(qw -> qw
                            .eq(AnswerPaperQuestion::getQuestionType, 3)
                            .or()
                            .eq(AnswerPaperQuestion::getQuestionType, 4))
            );
            //查回答问题内容
            for (AnswerPaperQuestion answerPaperQuestion : answerPaperQuestionList) {
                answerPaperQuestion.setAnswerPaperChoice(
                        answerPaperChoiceService.getOne(Wrappers.lambdaQuery(AnswerPaperChoice.class)
                                .eq(AnswerPaperChoice::getAnswerPaperQuestionId, answerPaperQuestion.getId())
                        )
                );
            }
            answerPaper.setAnswerPaperQuestionList(answerPaperQuestionList);
        }

        //*查试题信息 只有填空题简答题需要批改
        Paper paper = paperService.getById(exam.getPaperId());

        List<PaperQuestion> paperQuestionList = paperQuestionService.list(Wrappers.lambdaQuery(PaperQuestion.class)
                .eq(PaperQuestion::getPaperId, exam.getPaperId())
                .and(qw -> qw
                        .eq(PaperQuestion::getQuestionType, 3)
                        .or()
                        .eq(PaperQuestion::getQuestionType, 4)
                )
        );
        //注入答案
        for (PaperQuestion paperQuestion : paperQuestionList) {
            paperQuestion.setPaperQuestionAnswerList(
                    paperQuestionAnswerService.list(Wrappers.lambdaQuery(PaperQuestionAnswer.class)
                            .eq(PaperQuestionAnswer::getQuestionId, paperQuestion.getId())
                    )
            );
        }
        paper.setPaperQuestionList(paperQuestionList);


        //*将试题信息连同其回答注入answerPaper
        for (AnswerPaper answerPaper : answerPaperList) {

            //错误的 浅拷贝
            //Paper paperClone = new Paper();
            //BeanUtils.copyProperties(paper, paperClone);

            // 将查到的试卷信息paper对象复制 深拷贝
            Paper paperClone = (Paper) SerializationUtils.clone(paper); //序列化本身及其依赖

            //查selected
            for (PaperQuestion paperQuestion : paperClone.getPaperQuestionList()) {
                for (AnswerPaperQuestion answerPaperQuestion : answerPaper.getAnswerPaperQuestionList()) {
                    if (paperQuestion.getId().equals(answerPaperQuestion.getQuestionId())) {
                        paperQuestion.setSelected(answerPaperQuestion.getAnswerPaperChoice().getAnswerValue());
                    }
                }
            }
            //将试题信息连同其回答注入answerPaper
            answerPaper.setPaper(paperClone);

            //注入student
            answerPaper.setStudent(studentService.getById(answerPaper.getStudentId()));

        }

        return ResultUtils.success("查询成功", answerPaperList);
    }

    //保存批改的答卷信息
    @ApiOperation("保存批改的答卷信息")
    @PostMapping("/commitCorrectAnswerPaperList")
    @Transactional
    public ResultVo commitCorrectAnswerPaperList(@RequestBody List<AnswerPaper> answerPaperList) {
        System.out.println(answerPaperList);

        //发起考试的老师 才能查看考生列表 才能批卷
        Long teacherId = examService.getById(answerPaperList.get(0).getExamId()).getTeacherId();

        //先查本答卷的试题全信息 (除选项内容信息)
        //1.查出 单选题 多选题 对应的 paper-> paperQuestionList -> List<paperQuestionAnswer> 答案对象
        Paper paperModel = new Paper();
        Long paperId = answerPaperList.get(0).getPaperId();
        List<PaperQuestion> paperQuestionList = paperQuestionService.list(Wrappers.lambdaQuery(PaperQuestion.class)
                .eq(PaperQuestion::getPaperId, paperId)
                //只查 选择题
                .and(qw -> qw
                        .eq(PaperQuestion::getQuestionType, 1)
                        .or()
                        .eq(PaperQuestion::getQuestionType, 2)
                )
        );
        for (PaperQuestion paperQuestion : paperQuestionList) {
            paperQuestion.setPaperQuestionAnswerList(
                    paperQuestionAnswerService.list(Wrappers.lambdaQuery(PaperQuestionAnswer.class)
                            .eq(PaperQuestionAnswer::getQuestionId, paperQuestion.getId())
                    )
            );
        }
        paperModel.setPaperQuestionList(paperQuestionList);

        //用于保存批改信息
        List<CorrectAnswerPaper> correctAnswerPaperList = new ArrayList<>();

        //本班 循环批卷
        for (AnswerPaper answerPaper : answerPaperList) {

            //初始化题目总分
            int singleSumScore = 0;
            int multipleSumScore = 0;
            int fillInSumScore = 0;
            int textSumScore = 0;

            //存correctAnswerPaper 并且获取自增Id
            CorrectAnswerPaper correctAnswerPaper = new CorrectAnswerPaper(null, answerPaper.getId(), teacherId, null, null);
            boolean saveFlag = correctAnswerPaperService.save(correctAnswerPaper);
            Long correctAnswerPaperId = null;
            if (saveFlag) {
                correctAnswerPaperId = correctAnswerPaper.getId();
            }

            //2.查出 单选题 多选题 对应的 answerPaper -> answerPaperQuestionList ->answerPaperChoice.answerValue 1,3,2,4
            Long answerPaperId = answerPaper.getId();
            List<AnswerPaperQuestion> answerPaperQuestionList = answerPaperQuestionService.list(Wrappers.lambdaQuery(AnswerPaperQuestion.class)
                    .eq(AnswerPaperQuestion::getAnswerPaperId, answerPaperId)
            );
            for (AnswerPaperQuestion answerPaperQuestion : answerPaperQuestionList) {
                answerPaperQuestion.setAnswerPaperChoice(
                        answerPaperChoiceService.getOne(Wrappers.lambdaQuery(AnswerPaperChoice.class)
                                .eq(AnswerPaperChoice::getAnswerPaperQuestionId, answerPaperQuestion.getId())
                        )
                );
            }

            //3.将答案对象和answerValue 进行对比 计算 单选题 多选题 的总分
            for (PaperQuestion paperQuestion : paperModel.getPaperQuestionList()) {
                for (AnswerPaperQuestion answerPaperQuestion : answerPaperQuestionList) {
                    //比较试题对应回答的正误
                    if (paperQuestion.getId().equals(answerPaperQuestion.getQuestionId())) {
                        if (paperQuestion.getQuestionType().equals("1")) {
                            //如果是单选题
                            String correctText = paperQuestion.getPaperQuestionAnswerList().get(0).getAnswerText();
                            String answerText = answerPaperQuestion.getAnswerPaperChoice().getAnswerValue();
                            if (correctText.equals(answerText)) {
                                //回答正确单选题加5分
                                singleSumScore += 5;
                            }

                        } else if (paperQuestion.getQuestionType().equals("2")) {
                            //如果是多选题

                            //参考答案list
                            String[] correctAnswers = new String[paperQuestion.getPaperQuestionAnswerList().size()];
                            for (int i = 0; i < paperQuestion.getPaperQuestionAnswerList().size(); i++) {
                                correctAnswers[i] = paperQuestion.getPaperQuestionAnswerList().get(i).getAnswerText();
                            }
                            System.out.println("参考答案list" + Arrays.toString(correctAnswers));

                            //回答答案list
                            String[] answerTexts = answerPaperQuestion.getAnswerPaperChoice().getAnswerValue().split(",");
                            System.out.println("回答答案list" + Arrays.toString(answerTexts));

                            if (correctAnswers.length > answerTexts.length) {
                                //1.选项个数不一致 漏选 回答选项的顺序可能是乱序
                                boolean found = true;
                                for (String answerText : answerTexts) {
                                    boolean foundOne = false;
                                    for (String correctAnswer : correctAnswers) {
                                        //找到一个就 判断有效
                                        if (correctAnswer.equals(answerText)) {
                                            foundOne = true;
                                            break;
                                        }
                                    }
                                    //没有找到一个选项匹配 判错
                                    if (!foundOne) {
                                        found = false;
                                        break;
                                    }
                                }
                                //选错 不赋分
                                if (found) {
                                    //全部选对 但是漏选
                                    multipleSumScore += 2;
                                }
                            } else if (correctAnswers.length == answerTexts.length) {
                                //1.选项个数一致  回答选项的顺序可能是乱序
                                boolean found = true;
                                for (String answerText : answerTexts) {
                                    boolean foundOne = false;
                                    for (String correctAnswer : correctAnswers) {
                                        //找到一个就 判断有效
                                        if (correctAnswer.equals(answerText)) {
                                            foundOne = true;
                                            break;
                                        }
                                    }
                                    //没有找到一个选项匹配 判错
                                    if (!foundOne) {
                                        found = false;
                                        break;
                                    }
                                }
                                //选错 不赋分
                                if (found) {
                                    //全部选对
                                    multipleSumScore += 5;
                                }
                            }  //其他情况 选多 不选 均不赋值

                        }
                    }
                }
            }

            //用于saveBatch
            List<CorrectAnswerPaperScore> correctAnswerPaperScoreList = new ArrayList<>();
            //填空题 简答题 保存批卷信息
            for (PaperQuestion paperQuestion : answerPaper.getPaper().getPaperQuestionList()) {
                if (paperQuestion.getQuestionType().equals("3")) {
                    Integer score = paperQuestion.getScore();
                    if (score != null) {
                        //保存简答题 填空题 分数
                        correctAnswerPaperScoreList.add(
                                new CorrectAnswerPaperScore(null, paperQuestion.getId(), correctAnswerPaperId, score)
                        );
                        //填空题
                        fillInSumScore += score;
                    }
                } else if (paperQuestion.getQuestionType().equals("4")) {
                    Integer score = paperQuestion.getScore();
                    if (score != null) {
                        //保存简答题 填空题 分数
                        correctAnswerPaperScoreList.add(
                                new CorrectAnswerPaperScore(null, paperQuestion.getId(), correctAnswerPaperId, score)
                        );
                        //填空题
                        textSumScore += score;
                    }
                }

            }
            //保存 CorrectAnswerPaperScore
            correctAnswerPaperScoreService.saveBatch(correctAnswerPaperScoreList);


            //保存各题目统计总分
            int[] scores = {0, singleSumScore, multipleSumScore, fillInSumScore, textSumScore};
            for (int i = 1; i <= 4; i++) {
                correctAnswerPaperInfoService.save(new CorrectAnswerPaperInfo(null, String.valueOf(i), scores[i], correctAnswerPaperId));
            }
            System.out.println("单选题得分：" + singleSumScore);
            System.out.println("多选题得分：" + multipleSumScore);
            System.out.println("填空题得分：" + fillInSumScore);
            System.out.println("简答题得分：" + textSumScore);
        }
        return ResultUtils.success("批改成功！");
    }

    //将批改结果 导出csv文件
    @ApiOperation("将批改结果 导出csv文件")
    @GetMapping("/upLoadCSVFile")
    public void uploadCSVFile(@RequestParam("id") Long id) throws Exception {

        //1. exam ->  examId -> answerPaperList
        List<AnswerPaper> answerPaperList = answerPaperService.list(Wrappers.lambdaQuery(AnswerPaper.class)
                .eq(AnswerPaper::getExamId, id)
        );

        //2. answerPaperList -> correctAnswerPaper -> List<correctAnswerPaperInfo>
        for (AnswerPaper answerPaper : answerPaperList) {
            //注入学生
            answerPaper.setStudent(
                    studentService.getById(answerPaper.getStudentId())
            );
            //查批改信息
            CorrectAnswerPaper correctAnswerPaper = correctAnswerPaperService.getOne(Wrappers.lambdaQuery(CorrectAnswerPaper.class)
                    .eq(CorrectAnswerPaper::getAnswerPaperId, answerPaper.getId())
            );
            //注入批改题目信息
            correctAnswerPaper.setCorrectAnswerPaperInfoList(
                    correctAnswerPaperInfoService.list(Wrappers.lambdaQuery(CorrectAnswerPaperInfo.class)
                            .eq(CorrectAnswerPaperInfo::getCorrectAnswerPaperId, correctAnswerPaper.getId())
                            //题目类型得分数据按数字排序
                            .orderByAsc(CorrectAnswerPaperInfo::getQuestionType)
                    )
            );
            answerPaper.setCorrectAnswerPaper(correctAnswerPaper);
        }

        //用空集合保存表格信息
        List<StatisticStudent> statisticStudentList = new ArrayList<>();

        for (int i = 1; i <= answerPaperList.size(); i++) {
            CorrectAnswerPaper correctAnswerPaper = answerPaperList.get(i - 1).getCorrectAnswerPaper();

            Long[] scores = new Long[4];
            for (int j = 0; j < 4; j++) {
                scores[j] = (long) correctAnswerPaper.getCorrectAnswerPaperInfoList().get(j).getSumScore();
            }

            StatisticStudent one = new StatisticStudent(
                   null,
                    answerPaperList.get(i - 1).getStudent().getUserName(),
                    scores[0] + scores[1] + scores[2] + scores[3],
                    scores[0],
                    scores[1],
                    scores[2],
                    scores[3]
            );
            statisticStudentList.add(one);
        }
        //按总分排序
        statisticStudentList = statisticStudentList.stream()
                .sorted(Comparator.comparingLong(StatisticStudent::getSumScore).reversed())
                .collect(Collectors.toList());
        Long num = 1L;
        for (StatisticStudent statisticStudent:statisticStudentList){
            statisticStudent.setNum(num++);
        }


        //*设置对应文件名
        Student student = studentService.getById(answerPaperList.get(0).getStudentId());
        Paper paper = paperService.getById(answerPaperList.get(0).getPaperId());
        String fileName=student.getYear()+"级_"+student.getMajorName()+"_"+student.getClassNum()+"班_"+paper.getPaperTitle()+"_成绩详情.csv";

        //逻辑判空
        if (!CollectionUtils.isEmpty(answerPaperList)) {
            // 定义表头数组
            String header[] = {
                    "排名",
                    "姓名",
                    "总分",
                    "单选题",
                    "多选题",
                    "填空题",
                    "简答题"
            };
            // 定义属性数组，对应表头中的每一列
            String properties[] = {
                    "num", // 排名
                    "studentName", // 学生名字
                    "sumScore",
                    "singleScore",
                    "multipleScore",
                    "fillInScore",
                    "textScore",
            };
            // 获取请求上下文中的响应对象
            ServletRequestAttributes requestAttributes = (ServletRequestAttributes)
                    RequestContextHolder.getRequestAttributes();
            // 创建适配器，用于将长整型数据转换为字符串
            CellProcessor longToStringAdapter = new CellProcessor() {
                @Override
                public <T> T execute(Object o, CsvContext csvContext) {
                    return (T) String.valueOf(o);
                }
            };

            // 定义处理器数组，包含每一列对应的处理器
            CellProcessor[] processor = new CellProcessor[]{
                    longToStringAdapter, // 将ID转换为字符串
                    null, // 不做处理
                    longToStringAdapter,
                    longToStringAdapter,
                    longToStringAdapter,
                    longToStringAdapter,
                    longToStringAdapter,
            };

            ReportCsvUtils.reportListCsv(
                    requestAttributes.getResponse(), // 将响应对象传递以编写CSV文件
                    header, // 指定CSV文件的标题/列名
                    properties, // 指定CashRecharge对象的属性/字段
                    fileName,
                    statisticStudentList, // 将要导出到CSV的CashRecharge记录列表
                    processor // 在CSV中为每个字段应用指定的处理器
            );
            System.out.println("666!" + answerPaperList);

            for (StatisticStudent statisticStudent:statisticStudentList){
                System.out.println(statisticStudent);
            }

        }


    }

    //统计批改过的试卷
    @ApiOperation("统计批改过的试卷-同分数学生排名相靠!")
    @GetMapping("/getMyCorrectAnswerPaperCount")
    public ResultVo getMyCorrectAnswerPaperCount(@RequestParam("teacherId") Long teacherId){
        int count = correctAnswerPaperService.count(Wrappers.lambdaQuery(CorrectAnswerPaper.class)
                .eq(CorrectAnswerPaper::getTeacherId, teacherId)
        );
        return ResultUtils.success("查询成功",count);
    }
}



